package com.newlink.building.login.ui.fragments

import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.text.method.HideReturnsTransformationMethod
import android.text.method.PasswordTransformationMethod
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.core.content.ContextCompat
import com.newlink.building.login.utils.Module_Login_AccountMemoryUtils
import com.newlink.building.login.R
import com.newlink.building.login.databinding.LayoutPasswordBinding
import com.newlink.building.login.event.SetKitPwdEvent
import com.newlink.building.login.mvp.contract.Module_Login_InputNewPwdContract
import com.newlink.building.common_base.base.BaseMvpFragment
import com.newlink.building.common_base.constant.Base_Constant
import com.newlink.building.common_base.ext.showToast
import com.newlink.building.common_base.ext.showToastImmediately
import com.newlink.building.common_base.model.bean.NewKitPasswordBean
import com.newlink.building.common_base.utils.DialogUtil
import com.newlink.building.common_base.utils.NLog
import com.newlink.building.common_base.utils.Base_Preference
import com.newlink.building.common_base.utils.RegexUtils
import com.newlink.building.common_base.utils.logDebug
import com.newlink.building.crypt.library_crypt.digest.Md5Crypt
import com.newlink.building.login.bean.UserAccountInfo
import com.newlink.building.login.mvp.presenter.Module_Login_InputNewPwdPresenter
import org.greenrobot.eventbus.EventBus

/**
 * @Author: admin
 * @Date: 2022/9/13
 * @Description: Kit 设备设置密码页面，用于用户为 Kit 账户设置或重置密码。
 * @License:  Copyright  1998 Fanvil Technology Co., Ltd. All rights reserved.
 */
class Module_Login_KitSetPasswordFragment :
    BaseMvpFragment<Module_Login_InputNewPwdContract.View, Module_Login_InputNewPwdContract.Presenter>(),
    Module_Login_InputNewPwdContract.View {

    // 视图绑定实例
    private lateinit var binding: LayoutPasswordBinding

    // 从 arguments 中获取的验证码 (短信或邮箱)
    private var verificationCode: String = ""

    // 账户信息列表，使用 Preference 委托进行持久化存储
    private var userAccountInfoList: MutableList<UserAccountInfo> by Base_Preference(
        Base_Constant.USER_ACCOUNT_INFO_LIST_KEY,
        mutableListOf(UserAccountInfo("", "", "", "", 0L, 1))
    )

    // 记住的邮箱账户，使用 Preference 委托进行持久化存储
    protected var emailAccount: String by Base_Preference(Base_Constant.REMEMBER_EMAIL_ACCOUNT, "")

    // 记住的密码值（MD5加密后），使用 Preference 委托进行持久化存储
    protected var passwordSaved: String by Base_Preference(Base_Constant.REMEMBER_PWD_VALUE, "")

    // 等待对话框，用于显示加载状态
    private val loadingDialog by lazy {
        DialogUtil.getWaitDialog(requireContext())
    }

    /**
     * Companion object 用于提供 Fragment 实例。
     */
    companion object {
        // Bundle 中用于传递验证码的键
        private const val ARG_VERIFICATION_CODE: String = "VERIFY_SMS_CODE"

        /**
         * 获取 KitSetPasswordFragment 的新实例。
         * @param verificationCode 验证码 (短信或邮箱)。
         * @return KitSetPasswordFragment 实例。
         */
        fun getInstance(verificationCode: String): Module_Login_KitSetPasswordFragment {
            val fragment = Module_Login_KitSetPasswordFragment()
            val bundle = Bundle().apply {
                putString(ARG_VERIFICATION_CODE, verificationCode)
            }
            fragment.arguments = bundle
            return fragment
        }
    }

    /**
     * 绑定布局文件并返回根视图。
     */
    override fun attachLayoutRes(): View {
        binding = LayoutPasswordBinding.inflate(layoutInflater)
        return binding.root
    }

    /**
     * 创建 Presenter 实例。
     */
    override fun createPresenter(): Module_Login_InputNewPwdContract.Presenter = Module_Login_InputNewPwdPresenter()

    /**
     * 初始化视图组件和设置监听器。
     */
    override fun initView(view: View) {
        verificationCode = requireArguments().getString(ARG_VERIFICATION_CODE, "")

        // 如果没有收到验证码，则屏蔽返回事件 (防止用户直接返回到非预期页面)
        if (verificationCode.isEmpty()) {
            shieldBackNavigation()
        }

        setupPasswordInputFields()
        setupPasswordVisibilityToggle()
        setupClearButtons()
        setupTextWatchers()
        setupConfirmButtonListener()
    }

    /**
     * 屏蔽 Android 系统的返回导航事件。
     * 通常用于强制用户完成当前流程。
     */
    private fun shieldBackNavigation() {
        requireActivity().onBackPressedDispatcher.addCallback(
            this,
            object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    // 拦截返回事件，不执行任何操作，阻止用户返回
                }
            })
    }

    /**
     * 初始化密码输入框的背景资源。
     */
    private fun setupPasswordInputFields() {
        binding.etPassword.setBackgroundResource(R.drawable.et_underline_selector)
        binding.etConfirmPassword.setBackgroundResource(R.drawable.et_underline_selector)
    }

    /**
     * 设置密码显示/隐藏切换功能。
     */
    private fun setupPasswordVisibilityToggle() {
        binding.ibEye.isEnabled = false // 默认眼睛图标为禁用状态（密码隐藏）
        binding.linearPwdDisplay.setOnClickListener {
            val isCurrentlyVisible = binding.ibEye.isEnabled // ibEye.isEnabled 表示当前密码是否可见
            binding.etPassword.transformationMethod =
                if (isCurrentlyVisible) PasswordTransformationMethod.getInstance() else HideReturnsTransformationMethod.getInstance()
            binding.etConfirmPassword.transformationMethod =
                if (isCurrentlyVisible) PasswordTransformationMethod.getInstance() else HideReturnsTransformationMethod.getInstance()
            binding.ibEye.isEnabled = !isCurrentlyVisible // 切换眼睛图标状态
        }
    }

    /**
     * 设置清除按钮的点击事件，用于清空密码输入框内容。
     */
    private fun setupClearButtons() {
        binding.ivPasswordNewClear.setOnClickListener {
            binding.etPassword.text?.clear()
        }
        binding.ivPasswordConfirmClear.setOnClickListener {
            binding.etConfirmPassword.text?.clear()
        }
    }

    /**
     * 设置密码输入框的文本变化监听器，用于实时更新 UI 状态。
     */
    private fun setupTextWatchers() {
        binding.etPassword.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
            override fun afterTextChanged(s: Editable?) {
                updateButtonAndErrorState()
            }
        })

        binding.etConfirmPassword.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
            override fun afterTextChanged(s: Editable?) {
                updateButtonAndErrorState()
            }
        })
    }

    /**
     * 设置确认按钮的点击事件和密码验证逻辑。
     */
    private fun setupConfirmButtonListener() {
        binding.btnRegisterConfirm.setOnClickListener {
            val newPassword = binding.etPassword.text?.toString()
            val confirmPassword = binding.etConfirmPassword.text?.toString()

            // 检查密码是否为空
            if (newPassword.isNullOrEmpty()) {
                binding.etPassword.error = resources.getString(R.string.user_reset_pwd_error_format)
                return@setOnClickListener
            }
            if (confirmPassword.isNullOrEmpty()) {
                binding.etConfirmPassword.error =
                    resources.getString(R.string.user_reset_pwd_error_format)
                return@setOnClickListener
            }
            // 检查两次密码是否一致
            if (newPassword != confirmPassword) {
                showConfirmPasswordMismatchError(true)
                return@setOnClickListener
            }

            // 检查密码长度
            if (newPassword.length !in 8..36) {
                showToast(getString(R.string.set_password_length))
                return@setOnClickListener
            }
            // 检查密码复杂度
            if (!RegexUtils.checkPassword(newPassword)) {
                showToast(getString(R.string.set_password_length)) // 应该使用更具体的提示
                return@setOnClickListener
            }

            NLog.e("新密码: $newPassword")
            NLog.e("确认密码: $confirmPassword")

            // 对密码进行 MD5 加密
            val hashedPwd1 = Md5Crypt.md5(newPassword)
            val hashedPwd2 = Md5Crypt.md5(newPassword) // 确认密码也用相同方式加密以匹配 API 要求

            NLog.e("MD5 加密后的密码1: $hashedPwd1")
            NLog.e("MD5 加密后的密码2: $hashedPwd2")

            loadingDialog.show() // 显示加载对话框

            // 调用 Presenter 发送设置新密码请求
            // 注意: accessToken 和 userId 假定为在 Activity 或其他可访问的父类中提供
            mPresenter?.sendNewKitPwd(
                accessToken,
                NewKitPasswordBean(userId, hashedPwd1, hashedPwd2)
            )
        }
    }

    /**
     * 显示或隐藏确认密码不匹配的错误提示。
     * @param showError 是否显示错误提示。
     */
    private fun showConfirmPasswordMismatchError(showError: Boolean) {
        binding.linearPwdDifferent.visibility = if (showError) View.VISIBLE else View.GONE
        binding.linearPwdRule.visibility = if (showError) View.GONE else View.VISIBLE // 规则提示与错误提示互斥
        // 根据错误状态设置下划线的颜色
        val lineColorRes = if (showError) R.color.red else R.color.color_e2e2e8
        binding.viewLine1.background = ContextCompat.getDrawable(requireContext(), lineColorRes)
        binding.viewLine2.background = ContextCompat.getDrawable(requireContext(), lineColorRes)
    }

    /**
     * 根据输入框内容更新确认按钮和清除图标的状态。
     */
    private fun updateButtonAndErrorState() {
        showConfirmPasswordMismatchError(false) // 每次输入时隐藏错误提示

        val newPasswordInput = binding.etPassword.text?.trim().toString()
        val confirmPasswordInput = binding.etConfirmPassword.text?.trim().toString()

        binding.ivPasswordNewClear.visibility =
            if (newPasswordInput.isNotEmpty()) View.VISIBLE else View.GONE
        binding.ivPasswordConfirmClear.visibility =
            if (confirmPasswordInput.isNotEmpty()) View.VISIBLE else View.GONE

        // 只有当两个密码输入框都有内容时，确认按钮才可用
        binding.btnRegisterConfirm.isEnabled =
            newPasswordInput.isNotEmpty() && confirmPasswordInput.isNotEmpty()
    }

    /**
     * 生命周期回调：Fragment 被附加到 Activity 时。
     */
    override fun onAttach(context: Context) {
        super.onAttach(context)
    }

    /**
     * 懒加载方法，当前未实现具体逻辑。
     */
    override fun lazyLoad() {
        // 无需额外的懒加载逻辑
    }

    /*
     * 以下是 InputNewPwdContract.View 接口的实现方法
     */

    /**
     * 设置新密码成功回调。
     * 显示成功 Toast，通过 EventBus 发送重置密码成功事件，保存账户信息，并隐藏加载对话框。
     */
    override fun setNewPwdSuccess() {
        showToastImmediately(R.string.set_password_success)
        logDebug<Module_Login_KitSetPasswordFragment>("set password success")

        val pwdMd5 = Md5Crypt.md5(binding.etPassword.text.toString())
        EventBus.getDefault().post(SetKitPwdEvent(true, pwdMd5))
        saveAccountInformation(pwdMd5) // 保存账户信息
        loadingDialog.dismiss()
    }

    /**
     * 设置新密码失败回调。
     * 显示失败原因 Toast，并隐藏加载对话框。
     * @param reason 失败原因的字符串，可为空。
     */
    override fun setNewPwdFailed(reason: String?) {
        logDebug<Module_Login_KitSetPasswordFragment>("set password failed")
        reason?.let {
            showToastImmediately(it)
        }
        loadingDialog.dismiss()
    }

    /**
     * 保存用户账户信息到本地存储。
     * @param encryptedPassword MD5 加密后的密码。
     */
    private fun saveAccountInformation(encryptedPassword: String) {
        // userInfoData, accessToken, userId 假定为在宿主 Activity 或其他可访问的父类中提供
        val email = userInfoData.email
        val mobile = userInfoData.mobile // 假设 mobile 在 userInfoData.data 中
        val userName = when {
            email.isNotEmpty() -> email
            mobile.isNotEmpty() -> mobile
            else -> ""
        }
        emailAccount = userName // 记住账户名称（可能是邮箱或手机号）
        passwordSaved = encryptedPassword // 记住加密后的密码

        // 更新 userInfoData 的设置密码标志
        val tempUserInfoData = userInfoData.copy()
        tempUserInfoData.setPwdFlag = true
        userInfoData = tempUserInfoData

        // 使用 AccountMemoryUtils 保存账户详情
        userAccountInfoList = Module_Login_AccountMemoryUtils.saveAccountInfo(
            userName,
            userId.toString(),
            email,
            encryptedPassword,
            userInfoData.userCategory,
            userAccountInfoList,
            mobile
        )
    }
}